import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server extends Thread implements MyObserver, MyObservable{
	public ServerSocket serverSocket;
	protected Socket client;
	private int SERVERPORT = 45658;
	public static ArrayList<String> connections ;
	public static String downloadFolder="";
	
	private PrintWriter out ;
	List<MyObserver> observers;
	List<ServiceThread> serviceThreadList;
	
	public static final int MaxAccepts = 1;
	public Server(String ipAddress){
		
		serviceThreadList = new ArrayList<ServiceThread>();
		
		observers = new ArrayList<MyObserver>();
		
		connections = new ArrayList<String>();
		//set download folder to current folder by default:
		downloadFolder ="";
		System.out.println("Starting server...");
		try {
			InetAddress inetaddr = InetAddress.getByName(ipAddress);
			serverSocket = new ServerSocket(SERVERPORT,1,inetaddr);
			
		} catch (IOException e) {
			e.printStackTrace();
			//notify observers in order to keep a good log:
			//setChanged();
			notifyObservers(e.getMessage());
			System.err.println("ERROR opening server socket");
		}
	}
	public Server(String ipAddress, int portno){
		
		connections = new ArrayList<String>();
		//set download folder to current folder by default:
		File down = null;
		try {
			down = new File(new File(".").getCanonicalPath());
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		downloadFolder =down.toString();
		System.out.println("Starting server...");
		try {
			serverSocket = new ServerSocket(portno);
		} catch (IOException e) {
			e.printStackTrace();
			//notify observers in order to keep a good log:
			//setChanged();
			notifyObservers(e.getMessage());
			System.err.println("ERROR opening server socket");
		}
	}
	
	public PrintWriter getOutput(){
		return this.out;
	}
	
	public void run(){
		while(true){
			for (int i = 0 ; i < MaxAccepts; i++){
				Socket clientSocket = null;
				try{
					clientSocket = this.serverSocket.accept();
					ServiceThread st = new ServiceThread(clientSocket);
					st.start();
					this.serviceThreadList.add(st);
				}catch(IOException e){
					System.out.println("Error in accept");
				}
			}
			/*
			for (ServiceThread st : this.serviceThreadList){
				try{
					st.join();
				} catch(Exception e){
					System.out.println("Error in thread join");
				}
			}
			*/
			
		}
	}
	
	public static void startServer(String ip){
		Server newServ = new Server(ip);
		newServ.start();
		try{
			newServ.join();
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
	}
	
	public void stopServer(){
		
		try {
			//wait(300);
			this.interrupt();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("HERE");
			e.printStackTrace();
		}
	}
	
	@Override
	public void update(MyObservable o, Object arg) {
		// TODO Auto-generated method stub
		if( arg instanceof String){
			downloadFolder = (String)arg;
			downloadFolder += File.separator;
			System.out.println("New download folder: "+downloadFolder);
		}
	}
	@Override
	public void addObserver(MyObserver o) {
		// TODO Auto-generated method stub
		observers.add(o);
		
	}
	@Override
	public void notifyObservers(Object o) {
		// TODO Auto-generated method stub
		for(MyObserver obs : observers){
			obs.update(this, o);
		}
	}
	@Override
	public void notifyObservers() {
		// TODO Auto-generated method stub
		//Nothing to be done here
	}
}
